#!/usr/bin/perl

# ---------- Init variables -------
#my $version = "0.0001";
# ---------- external readable parameters -------
## Functions
##-------------------------------------------------------
#
# stict syntax checking.
require Exporter;
use strict;
use SIM_settings;
use SIM_base;
use SIM_cgi;
use CGI qw(param);

#my $httpUser = $ENV{'REMOTE_USER'} || die "Oops no env found for SREMOTE_USER.";
my $module = $ARGV[0];
my $tool = $ARGV[1];
my $action = $ARGV[2];
my $option1 = $ARGV[3];
my $option2 = $ARGV[4];
my $option3 = $ARGV[5];
my $option4 = $ARGV[6];

my @ianaInfo = ();

# info for reporting function
my @rangeList = ();
my %rangeId = ();
my %rangeStart = ();
my %rangeStop = ();
my %portId = ();
my %ipType = ();

sub printHead {
  my $dispHead = "@_[0]";
  my $linkColor = "black";
  print("
        <TABLE WIDTH=100% BORDER=0 CELLSPACING=0><TR BGCOLOR=#EEEEEE><TD COLSPAN=3><CENTER>
        Options: analyse");
  printEntry("syslog", "Gather healthcheck, activation / deactivation info.", "$module", "$tool+syslog", "2", "$module", "$tool+$action", "", "line", "", $linkColor);
  printEntry("display", "Gather healthcheck, activation / deactivation info.", "$module", "$tool+display", "2", "$module", "$tool+$action", "", "line", "/", $linkColor);
  print("
	</TD></TR>
	</TABLE>
	<CENTER>
        ");
}

sub readIana {
  open( IANA, $SIMparam{'SIMianaPorts'} );
  @ianaInfo = <IANA>;
  close(IANA);

}

sub dotFormatted
{
  # sub to create formatting of numbers
  # found on www.willmaster.com
  my $delimiter = '.'; # replace comma if desired
  my($n,$d) = split /\./,shift,2;
  my @a = ();
  while($n =~ /\d\d\d\d/)
  {
    $n =~ s/(\d\d\d)$//;
    unshift @a,$1;
  }
  unshift @a,$n;
  $n = join $delimiter,@a;
  $n = "$n\.$d" if $d =~ /\d/;
  return $n;
}


sub shortIp {
  my $ipAddr = "@_[0]";
# print("$ipAddr ");
  my @ips = split('\.', $ipAddr);
  my @sIp = ();
  foreach my $entry (@ips) {
    $entry =~ s/^0*//g;
    if ( "$entry" eq "" ) { $entry = "0"; }
#   print("$entry;");
    push( @sIp, $entry );
  }
  my $return = join('.', @sIp);
  return $return;
}

sub displayShortMenu {
  my $typeDir = "@_[0]";
  my $device = "@_[1]";
  my $protType = "@_[2]";
  my $entry = "@_[3]";
  my $linkColor = "black";
  print("Shortlink:<FONT COLOR=#444444> <B>==&gt;</B> </FONT>");
  if (( "$typeDir" ne "" ) and ( "$typeDir" ne "none" )) {
    print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir>$typeDir</A>");
    if ( "$device" ne "" ) {
      print("<FONT COLOR=#444444> <B>==&gt;</B> </FONT>");
      print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device>$device</A>");
      if ( "$protType" ne "" ) {
        print("<FONT COLOR=#444444> <B>==&gt;</B> </FONT>
	  <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+source>Source</A> /
	  <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+dest>Destination</A> /
	  <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+port>Protocol port</A> /
	  <A HREF=$httpScriptName?$module+$tool+report+$typeDir+$device>Report</A>
	      ");
	if (( "$entry" eq "" ) or ( "$entry" eq "AllDetails" ) or ( "$entry" eq "matrix" )) {
	  print(" | <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+$protType+summary>Summary</A> ");
	}
	if (( "$entry" eq "" )  or ( "$entry" eq "summary" ) or ( "$entry" eq "AllDetails" )) {
          print(" | <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+$protType+matrix>Matrix</A> ");
        }
	if (( "$entry" eq "" ) or ( "$entry" eq "summary" ) or ( "$entry" eq "matrix" )) {
	  print(" | <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+$protType+AllDetails>All details</A> ");
	}
        if ( "$entry" ne "" ) {
	  my $dispEntry = shortIp($entry);
	  print("<FONT COLOR=#444444> <B>==&gt;</B> </FONT>");
	  print("$dispEntry");
	  my $baseDir = "$SIMparam{'SIMtrafficAnalyserDir'}/$typeDir/$device";
	  if (( "$protType" eq "source" )  and ( -d "$baseDir/dest/$entry" )) {
	    print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+dest+$entry>Destination</A> ");
	  } elsif (( "$protType" eq "dest" ) and ( -d "$baseDir/source/$entry" )) {
	    print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+source+$entry>Source</A> ");
	  }
	}
      }
    }
  }
  print("<HR>");
}

sub getShortName {
  my $ipAddr = "@_[0]";
  my $ipDir = getIpDir( $ipAddr );
  if ( -f "$ipDir/dnsname.txt" ) {
    my $dnsInfo = catFileLine("$ipDir/dnsname.txt");
    my ( $type, $shortName, $domain ) = split(' ', $dnsInfo);
    return $shortName;
  } else {
    return("-");
  }
}

sub detail {
  my $typeDir = "@_[0]";
  my $device = "@_[1]";
  my $file = "@_[2]";
  my ( $sourceIp, $rest ) = split('-', $file);
  my $dataFile = "$SIMparam{'SIMtrafficAnalyserDir'}/$typeDir/$device/source/$sourceIp/$file";
  if ( ! -f $dataFile ) {
    print(" Oops, no data found for $file in device $device ");
  } else {
    print("<PRE>");
    system(" cat $dataFile ");
    print("</PRE>");
  }
}

sub getFileSummary {
  # this will get summary info for the data file.
  my $baseDir = "@_[0]";
  my $typeDir = "@_[1]";
  my $device = "@_[2]";
  my $entry = "@_[3]";
  my $outFile = "@_[4]";
  my ( $sourceIp, $destIp, $proto, $port ) = split('-', $entry);
  my $dataFile = "$baseDir/$typeDir/$device/source/$sourceIp/$entry";
  my $packets = 0;
  my $bytes = 0;
  my @hours = qw( 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 );
  my %timeBytes = ();
  my $lastData = "-";
  my $firstData;
  foreach my $entry (@hours) {
    $timeBytes{$entry} = "0";
  }

  open( IN, $dataFile );
  my @info = <IN>;
  close IN;
  foreach my $line (@info) {
    chomp $line;
    my @word = split(' ', $line);
    my ( $time, $dummy ) = split( "\:", $word[2]);
#    print("<TR><TD>$word[2], $time</TD></TR>");
    if ( "$word[0]" eq "netflow-5" ) {
      $packets = $packets + $word[10];
      $bytes = $bytes + $word[9];
      $timeBytes{$time} = $timeBytes{$time} + $word[9];
      if ( "$firstData" eq "" ) { $firstData = $word[2]; }
      $lastData = "$word[2]";
    } elsif ( "$word[0]" eq "asa-teardown" ) {
      $packets = $packets + $word[8];
      $bytes = $bytes + $word[9];
      $timeBytes{$time} = $timeBytes{$time} + $word[9];
      if ( "$firstData" eq "" ) { $firstData = $word[2]; }
      $lastData = "$word[2]";
    }
  }
  # create csv file for matrix data.
  if ( "$outFile" ne "" ) {
    my $dSourceIp = shortIp($sourceIp);
    my $sourceName = getShortName( $dSourceIp );
    my $dDestIp = shortIp($destIp);
    my $destName = getShortName( $dDestIp );
    my $dPort = shortIp($port);
    printFileLine($outFile, "append", "\"$sourceName\";\"$dSourceIp\";\"$destName\";\"$dDestIp\";\"$proto-$dPort\";$packets;$bytes;$firstData;$lastData\n");
  }
  return("$firstData $lastData $packets $bytes $timeBytes{'00'} $timeBytes{'01'} $timeBytes{'02'} $timeBytes{'03'} $timeBytes{'04'} $timeBytes{'05'} $timeBytes{'06'} $timeBytes{'07'} $timeBytes{'08'} $timeBytes{'09'} $timeBytes{'10'} $timeBytes{'11'} $timeBytes{'12'} $timeBytes{'13'} $timeBytes{'14'} $timeBytes{'15'} $timeBytes{'16'} $timeBytes{'17'} $timeBytes{'18'} $timeBytes{'19'} $timeBytes{'20'} $timeBytes{'21'} $timeBytes{'22'} $timeBytes{'23'}");
}

sub nodeTable {
  my $baseDir = "@_[0]";
  my $typeDir = "@_[1]";
  my $device = "@_[2]";
  my $protType = "@_[3]";
  my $entry = "@_[4]";
  chdir "$baseDir/$typeDir/$device/$protType/$entry";
  my @dirEntries = <*>;
  my $dataType = substr($typeDir, 0, 7);
  print("<TR BGCOLOR=#FFFF88 ALIGN=center>
                  <TD BGCOLOR=white></TD>
                  <TD COLSPAN=2>Source</TD><TD COLSPAN=2>Destination</TD><TD COLSPAN=4>Protocol / Port</TD>");
  if ( "$dataType" eq "netflow" ) {
    print("<TD>Packets</TD><TD>Bytes</TD><TD>First</TD><TD>Last</TD>");
  }
  print("</TR>");
  my $nameNum = 0;
  my $prevSourceIp;
  foreach my $entry (@dirEntries) {
    my ( $sourceIp, $destIp, $proto, $port ) = split('-', $entry);
    my $dispNum = "";
    if ( "$prevSourceIp" ne "$sourceIp" ) {
      $prevSourceIp = $sourceIp;
      $nameNum++;
      $dispNum = $nameNum;
    }
    my $dSourceIp = shortIp($sourceIp);
    my $sourceName = getShortName($dSourceIp);
    my $dDestIp = shortIp($destIp);
    my $destName = getShortName($dDestIp);
    my $dPort = $port; $dPort =~ s/^0*//g;
    my @portInfo = grep(/ $dPort\/$proto /, @ianaInfo);
    print("<TR BGCOLOR=#FFFFAA>
            <TD ALIGN=right BGCOLOR=white>$dispNum</TD>
            <TD><A HREF=$httpScriptName?mon+nodestatus+$dSourceIp>$sourceName</A></TD>
            <TD><A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+source+$sourceIp>$dSourceIp</A></TD>
            <TD><A HREF=$httpScriptName?mon+nodestatus+$dDestIp>$destName</A></TD>
            <TD><A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+dest+$destIp>$dDestIp</A></TD>
            <TD>$proto</TD>
            <TD ALIGN=right><A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+port+$port-$proto>$dPort</A></TD>
          ");
    if ( "$portInfo[0]" ne "" ) {
      my ( $protName, $rest ) = split(' ', $portInfo[0]);
      print("<TD>$protName</TD>");
    } else {
      print("<TD></TD>");
    }
#   my $dataFile = "$baseDir/$typeDir/$device/source/$sourceIp/$entry";
    my $sumData = getFileSummary( $baseDir, $typeDir, $device, $entry );
    my ($firstData, $lastData, $packets, $bytes) = split(' ', $sumData);
    my $dispBytes = dotFormatted($bytes);
    my $dataInfo = "<TD ALIGN=right>$packets</TD><TD ALIGN=right>$dispBytes</TD><TD>$firstData</TD><TD>$lastData</TD>";
    print(" <TD><A HREF=$httpScriptName?$module+$tool+detail+$typeDir+$device+$entry>(*)</A></TD>
         $dataInfo
         </TR>");
  }
}

sub display {
  my $typeDir = "@_[0]";
  my $device = "@_[1]";
  my $protType = "@_[2]";
  my $entry = "@_[3]";
  my $baseDir = "$SIMparam{'SIMtrafficAnalyserDir'}";
  if ( ! -d $baseDir ) {
    print("Oops, no analysed data found.");
  } elsif (( "$typeDir" eq "" ) or ( "$typeDir" eq "none" )) {
    chdir $baseDir;
    print("<H2>Please select an section below</H2>");
    displayShortMenu( $typeDir, $device, $protType, $entry );
    my @dirEntries = <*>;
    foreach my $entry (@dirEntries) {
      print(" <A HREF=$httpScriptName?$module+$tool+$action+$entry>$entry</A> <BR>");
    }
  } elsif (( "$device" eq "" ) and ( -d "$baseDir/$typeDir" )) {
    print("<H2>Please select the device below</H2>");
    displayShortMenu( $typeDir, $device, $protType, $entry );
    chdir "$baseDir/$typeDir";
    my @dirEntries = <*>;
    foreach my $entry (@dirEntries) {
      print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$entry>$entry</A> <BR>");
    }
  } elsif (( "$protType" eq "" ) and ( -d "$baseDir/$typeDir/$device" )) {
    print("<H2>Please select the section</H2>");
    displayShortMenu( $typeDir, $device, $protType, $entry );
    print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+source>Source</A> <BR>");
    print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+dest>Destination</A> <BR>");
    print(" <A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+port>Protocol port</A> <BR>");
    print(" <A HREF=$httpScriptName?$module+$tool+report+$typeDir+$device>Report</A> <BR>");
  } elsif ((( "$entry" eq "" ) or ( "$entry" eq "summary" ) or ( "$entry" eq "matrix" )) and ( -d "$baseDir/$typeDir/$device/$protType" )) {
    &readIana;
    print("<H2>Please select an entry</H2>");
    displayShortMenu( $typeDir, $device, $protType, $entry );
    chdir "$baseDir/$typeDir/$device/$protType";
    my @dirEntries = <*>;
#   @dirEntries = sort(@dirEntries);
    my $outFile = "Sipman-$SIMparam{'SIMmanDomain'}-traffic-$typeDir-$device-$protType-$entry.csv";
    my $outDetailsFile = "Sipman-$SIMparam{'SIMmanDomain'}-details-$typeDir-$device-$protType-$entry.csv";
    printFileLine("$SIMparam{'SIMgraphDir'}/$outDetailsFile","quiet","sourceName;sourceIp;destName;destIp;proto-port;packets;bytes;firstData;lastData\n");
    open( INFO, ">$SIMparam{'SIMgraphDir'}/$outFile" ) || die "Oops, could not open $outFile to save info.";
    print("<TABLE>");
    my $outLine;
    my $headerColor = "#AAEEEE";
    if (( "$entry" eq "summary" ) or ( "$entry" eq "matrix" )) {
      if ( "$entry" eq "matrix" ) {
        print("<TR ALIGN=center><TD COLSPAN=3></TD><TD COLSPAN=24>bits per seccond, per hour.</TD></TR>");
      }
      print("<TR ALIGN=center BGCOLOR=$headerColor><TD>Device</TD><TD>Ip address</TD><TD>Bytes</TD>");
      $outLine = "Device;Ip address;Bytes";
      if ( "$entry" eq "matrix" ) {
        foreach my $entry (0 .. 23) {
          print("<TD>$entry</TD>");
          $outLine = "$outLine;$entry";
        }
      }
      print("<TD>Protocols<FONT COLOR=$headerColor>---------------------------------------------------------------------------</FONT></TD></TR>\n");
      print INFO ("$outLine;Protocols\n");
    }
    my $grandTotalBytes = 0;
    my @grandTotalHourBps = ();
    foreach my $dirEntry (@dirEntries) {
#     my $dispEntry = $entry;
#     if ( "$protType" eq "port" ) { $dispEntry =~ s/^*0//g; }
      my $dispEntry = shortIp($dirEntry);
      $outLine = "";
      print("<TR>");
      if (( "$protType" eq "dest" ) or ( "$protType" eq "source" )) {
        my $dispName = getShortName($dispEntry);
	print("<TD VALIGN=top>$dispName</TD>");
        $outLine = $dispName;
      } elsif ( "$protType" eq "port" ) {
	my ( $portNum, $proto ) = split('-', $dispEntry);
	my $dPort = shortIp($portNum);
        my @portInfo = grep(/ $dPort\/$proto /, @ianaInfo);
	my ( $protName, $rest ) = split(' ', $portInfo[0]);
	print("<TD VALIGN=top>$protName</TD>");
        $outLine = $protName;
      }
      print("<TD VALIGN=top><A HREF=$httpScriptName?$module+$tool+$action+$typeDir+$device+$protType+$dirEntry>$dispEntry</A></TD>");
      $outLine = "$outLine;$dispEntry";
      # Display the sumary info (will need to add cache file.)
      if (( "$entry" eq "summary" ) or ( "$entry" eq "matrix" )) {
        chdir "$baseDir/$typeDir/$device/$protType/$dirEntry";
        my @sumList = <*>;
        my $totalBytes = 0;
	my %protList = ();
        my @sumMatrix = ();
        foreach my $sumEntry (@sumList) {
	  my ( $srcIp, $destIp, $protType, $protNum ) = split('-', $sumEntry);
	  my $dispProtNum = shortIp($protNum);
          $protList{"$protNum-$protType"} = "$protType-$dispProtNum";
          my $sumData = getFileSummary( $baseDir, $typeDir, $device, $sumEntry, "$SIMparam{'SIMgraphDir'}/$outDetailsFile" );
          my ($firstData, $lastData, $packets, $bytes, $matrix) = split(' ', $sumData, 5);
          if ( "$entry" eq "matrix" ) {
            my @timeMatrix = split(' ', $matrix);
            my $matrNum = 0;
            foreach my $entry (@timeMatrix) {
              $sumMatrix[$matrNum] = $sumMatrix[$matrNum] + $entry;
              $matrNum++;
            }
          }
          $totalBytes = $totalBytes + $bytes;
        }
        $grandTotalBytes = $grandTotalBytes + $totalBytes;
        my $dispBytes = dotFormatted($totalBytes);
        print("<TD VALIGN=top ALIGN=right>$dispBytes</TD>");
        $outLine = "$outLine;$totalBytes";
        if ( "$entry" eq "matrix" ) {
          my $num = 0;
          foreach my $entry (@sumMatrix) {
            $grandTotalHourBps[$num] = $grandTotalHourBps[$num] + $entry;
            $num++;
            my $bitsPerSec = $entry / 450;
            $bitsPerSec = sprintf("%.0f", $bitsPerSec);
            my $dispBitsPerSec;
            if ( "$bitsPerSec" ne "0" ) {
              $dispBitsPerSec = dotFormatted($bitsPerSec);
            } else {
              $bitsPerSec = "";
            }
            print("<TD VALIGN=top ALIGN=right BGCOLOR=#EEEEEEE>$dispBitsPerSec</TD>");
            $outLine = "$outLine;$bitsPerSec";
          }
        } 
        print("<TD>");
        $outLine = "$outLine;";
	my $num = 0;
	foreach my $key (sort keys %protList ) {
	  print("$protList{$key} ");
          $outLine = "$outLine $protList{$key}";
	  $num++;
	  if ( $num >= 10 ) {
	    print(" ..... ");
            $outLine = "$outLine .....";
	    last;
	  }
	}
	print("</TD>");
      }
      print("</TR>");
      print INFO ("$outLine\n");
    }
    if ( "$grandTotalBytes" ne "0" ) {
      my $dispBytes = dotFormatted($grandTotalBytes);
      print("<TR BGCOLOR=$headerColor><TD COLSPAN=2><B>Total traffic</B></TD><TD ALIGN=right>$dispBytes</TD>");
      $outLine = ";Total traffic;$grandTotalBytes";
      if ( "$entry" eq "matrix" ) {
        my $num = 0;
        foreach my $entry (@grandTotalHourBps) {
          $entry = $entry / 450;
          $entry = sprintf("%.0f", $entry);
          my $dispBytes = dotFormatted($entry);
          print("<TD>$dispBytes</TD>");
          $outLine = "$outLine;$entry";
        }
      }
      print("</TR>");
      print INFO ("$outLine\n");
    }
    close INFO;
    print("<TR><TD COLSPAN=30 BGCOLOR=#AAAAAA ALIGN=right>CSV: <A HREF=/graphs/$outFile>$outFile</A>
                 / DETAILS CSV: <A HREF=/graphs/$outDetailsFile>$outDetailsFile</A>
               </TD></TR>");
    print("</TABLE>");
  } elsif (( "$entry" eq "AllDetails" ) and ( -d "$baseDir/$typeDir/$device/$protType" )) {
    chdir "$baseDir/$typeDir/$device/$protType";
    my @dirEntries = <*>;
    print("<TABLE>");
    foreach my $entry (@dirEntries) {
      nodeTable( $baseDir, $typeDir, $device, $protType, $entry );
    }
    print("</TABLE>");
  } elsif (( "$entry" ne "" ) and ( -d "$baseDir/$typeDir/$device/$protType/$entry" )) {
    &readIana;
    my $dispEntry = shortIp($entry);
    print("<H2>Info for $device, $protType = $dispEntry.</H2>");
    displayShortMenu( $typeDir, $device, $protType, $entry );
    print("<TABLE>");
    nodeTable( $baseDir, $typeDir, $device, $protType, $entry );
    print("</TABLE>");
  } else {
    print("$module+$tool+$action+$typeDir+$device+$protType+$entry");
  }
  print("<P>");
}

sub analyseSyslog {
  my $syslogDir = "@_[0]";
  my $device = "@_[1]";
  my $baseSyslogDir = $SIMparam{'SIMsyslogDir'};
  if ( ! -d $baseSyslogDir ) {
    print("Oops, no syslog dir found.");
  } elsif (( "$syslogDir" eq "" ) or ( "$syslogDir" eq "none" )) {
    chdir $baseSyslogDir;
    my @dirEntries = <*>;
    print("<H2>Please select the syslog directory below</H2>");
    foreach my $entry (@dirEntries) {
      print(" <A HREF=$httpScriptName?$module+$tool+$action+$entry>$entry</A> <BR>");
    }
  } elsif (( "$device" eq "" ) and ( -d "$baseSyslogDir/$syslogDir" )) {
    print("<H2>Please select the device below</H2>");
    chdir "$baseSyslogDir/$syslogDir";
    my @dirEntries = <*>;
    foreach my $entry (@dirEntries) {
      print(" <A HREF=$httpScriptName?$module+$tool+$action+$syslogDir+$entry>$entry</A> <BR>");
    }
# } elsif (( "$device" ne "" ) and ( -f "$baseSyslogDir/$syslogDir/$device/all-messages" )) {
  } elsif ( "$device" ne "" ) {
    print("<H2>Analysing syslogfile for $device.</H2>");
    my $baseDir = "$SIMparam{'SIMtrafficAnalyserDir'}/$syslogDir/$device";
    if ( -d "$baseDir.old" ) {
      print("<BR>Previous old data found, removing it in the background...");
      my $statusDate = printDate( time, "logdate" );
      system(" mv $baseDir.old $baseDir.old.$statusDate ");
      system(" rm -fR $baseDir.old.$statusDate &");
      sleep 2;
    }
#   print("teardownTcp=$baseSyslogDir/$syslogDir/$device/*-302014, teardownUdp=$baseSyslogDir/$syslogDir/$device/*-302014<BR>");
    my @teardownTcp = <$baseSyslogDir/$syslogDir/$device/*-302014:>;
    my @teardownUdp = <$baseSyslogDir/$syslogDir/$device/*-302016:>;
    my @allTeardown = ( @teardownTcp, @teardownUdp );
    if ( ! -r "$allTeardown[0]" ) {
      print("Oops, problems reading $allTeardown[0] file for $device.");
    } else {
      if ( -d $baseDir ) { system(" mv $baseDir $baseDir.old "); }
      if ( ! -d "$baseDir/dbase" ) { system(" mkdir -p $baseDir/dbase"); }
      mkdir("$baseDir/source");
      mkdir("$baseDir/dest");
      mkdir("$baseDir/port");
      # read known-ports
      my %knownProts = ();
      my @portInfo = split(' ', $SIMparam{'SIMnetflowKnownPorts'});
      foreach my $entry (@portInfo) {
        $knownProts{$entry} = "known";
      }
#     print("<PRE>");
      foreach my $entry (@allTeardown) {
        open( IN, "$baseSyslogDir/$syslogDir/$device/all-messages" );
        my $num = 0;
        my $total = 0;
        my $centos = 0;
        while (my $line = <IN>) {
	  my @word = split(' ', $line);
	  if (( "$word[5]" eq "Teardown" ) and (( "$word[6]" eq "TCP" ) or ( "$word[6]" eq "UDP" )) and ( "$word[16]" ne "0" )) {
	    my $date = "$word[1]-$word[2]";
	    my $time = substr($word[3], 0, -1);
	    my $proto = lc($word[6]);
	    my $sourceInfo = $word[10];
	    my $destInfo = $word[12];
	    my $duration = $word[14];
	    my ($hour, $min, $sec) = split(':', $duration);
	    my $duration = $hour * 3600 + $min * 60 + $sec;
	    my $bytes = $word[16];
#	    print(" t:$time, $proto, $sourceInfo, $destInfo, $duration, $bytes<BR> ");
            my ( $sourceInt, $rest ) = split(':', $sourceInfo);
	    my ( $sourceIp, $sourcePort ) = split('/', $rest);
	    my ( $destInt, $rest ) = split(':', $destInfo);
	    my ( $destIp, $destPort) = split('/', $rest);
            my $reverse = "";
            # this is not 100% bullet proof, but it will correct order errors in CatOS syslog reporting.
            if (( "$knownProts{$sourcePort}" eq "known" ) or ((  $sourcePort < 1024 ) and ( "$sourcePort" ne "0" )) and ( "$destPort" ne "$sourcePort" )) {
              ( $sourceIp, $sourcePort, $destIp, $destPort ) = ( $destIp, $destPort, $sourceIp, $sourcePort );
              $reverse = "rev";
            }
	    my $longSourceIp = longIp($sourceIp);
	    my $longDestIp = longIp($destIp);
	    my $longDestPort = sprintf("%05d", $destPort);
#	    print(" $sourceIp, $sourcePort - $destIp, $destPort<BR> ");
	    if ( ! -d "$baseDir/source/$longSourceIp" ) {  mkdir "$baseDir/source/$longSourceIp"; }
	    if ( ! -d "$baseDir/dest/$longDestIp" ) { mkdir "$baseDir/dest/$longDestIp"; }
	    if ( ! -d "$baseDir/port/$longDestPort-$proto" ) { mkdir "$baseDir/port/$longDestPort-$proto"; }
	    my $found;
	    my $baseFile = "$longSourceIp-$longDestIp-$proto-$longDestPort";
	    if ( ! -f "$baseDir/source/$longSourceIp/$baseFile" ) { $found = "no"; }
	    printFileLine("$baseDir/source/$longSourceIp/$baseFile","append","asa-teardown $date $time $sourceIp $sourcePort $destIp $destPort $proto $duration $bytes $reverse\n");
	    if ( "$found" eq "no" ) {
	      touchFile("$baseDir/dest/$longDestIp/$baseFile");
	      touchFile("$baseDir/port/$longDestPort-$proto/$baseFile");
	    }
	  }
	  $num++;
	  if ( $num > 4 ) { 
            $num = 0; 
            $centos++;
            print(".");
            if ( $centos > 4 ) {
              $centos = 0;
              $total++;
              print(" $total ");
            } 
          }
        }
        close IN;
      }
      if ( -d "$baseDir.old" ) { 
        print("<BR>Removing old data...");
        system(" rm -fR $baseDir.old & ");
      }
      print("done.");
#     print("</PRE>");
    }
  } else {
    print("syslogDir: $syslogDir, device: $device. Oops, tool not yet ready, be patient for the next release, working on it.");
  }
  print("<P>");
# SIMtrafficAnalyserDir
}

sub numIpAddr {
  my $ipAddr = "@_[0]";
  my @ipArr = split('\.', $ipAddr);
  my $ipNum;
  foreach my $entry (@ipArr) {
    if ( "$ipNum" ne "" ) {
      $ipNum = $ipNum * 256 + $entry;
    } else { 
      $ipNum = $entry;
    }
  }
  return $ipNum;
}

sub numSecs {
  my $time = "@_[0]";
  my $secNum;
  my @timeArr = split('\:', $time);
  foreach my $entry (@timeArr) {
    if ( "$secNum" ne "" ) {
      # bevat rekenfout, heeft geen invloed op werking
      $secNum = $secNum * 60 + $entry;
    } else {
      $secNum = $entry;
    }
  }
  return $secNum;
}

sub testRange {
  my $testIp = "@_[0]";
# printDebug(0, "testRange: $testIp");
  if ( $ipType{$testIp} eq "" ) {
    my $ipNum = numIpAddr($testIp);
    foreach my $entry (@rangeList) {
#     print(" test: $entry, $ipNum, $rangeStart{$entry}, $rangeStop{$entry}.");
      if (( $rangeStart{$entry} <= $ipNum ) and ( $ipNum <= $rangeStop{$entry} )) {
        $ipType{$testIp} = $rangeId{$entry};
#       print(" newType:$ipType{$testIp} ");
        return $ipType{$testIp};
      }
    }
  } else {
#   print(" ipType:$ipType{$testIp} ");
    return $ipType{$testIp};
  }
}

sub countFileTotal { 
  my $fileName = "@_[0]";
  my $startTime = "@_[1]";
  my $stopTime = "@_[2]";
  my $totalBytes = 0;
# printDebug( 0, "countFileTotal: $fileName, $startTime, $stopTime. ");
  open( DET, $fileName ) || die "Oops, problem opening file $fileName.";
  my @lines = <DET>;
  close DET;
  foreach my $entry (@lines) {
    my @word = split(' ', $entry);
    my ( $time, $dummy ) = split( "\:", $word[2]);
    if (( "$word[0]" eq "netflow-5" ) or ( "$word[0]" eq "asa-teardown" )) {
      my $time = "$word[2]";
      my $lineSecs = numSecs( $time );
#     print(" test $time, $startTime < $lineSecs < $stopTime ");
      if (( "$word[9]" eq "bytes" ) or ( "$word[9]" eq "" )) {
        printDebug( 0, "Skip top line for $fileName ($word[9]).");
      } elsif (( $startTime <= $lineSecs ) and ( $lineSecs <= $stopTime )) {
        $totalBytes = $totalBytes + $word[9];
      # use the folowing lines to test the skip part.
#     } else {
#       print(" skip $time, $startTime < $lineSecs < $stopTime ");
      }
#   } else {
#     printDebug( 0, "Skip line for $fileName ($entry), ($word[9]).");
    }
  }
  printDebug(0, "found $totalBytes for $fileName");
  return $totalBytes;
}

sub report {
  my $typeDir = "@_[0]";
  my $device = "@_[1]";
  my $reportName = "@_[2]";
  print("<TABLE><TR><TD>");
  printDebug( 0, "typeDir: $typeDir, device:$device, reportName:$reportName.");
  my $baseDir = "$SIMparam{'SIMtrafficAnalyserDir'}/$typeDir/$device/source";
  if ( ! -f $SIMparam{'SIMtrafficAnalyserReport'} ) {
    printDebug( 0, "No definition file found, please define file SIMtrafficAnalyserReport.");
  } elsif ( ! -d $baseDir ) {
    printDebug( 0, "No basedir found for $device, please report this problem.");
  } else {
    open( IN, "$SIMparam{'SIMtrafficAnalyserReport'}" );
    my @info = <IN>;
    close IN;
    if ( "$reportName" eq "" ) {
      print("<H2>Select report name for $device.</H2><HR>");
      foreach my $entry (@info) {
        chomp( $entry );
        my ( $type, $rest ) = split(' ', $entry);
        if (( "$type" eq "reportname" ) and ( "$rest" ne "default" )) {
          print("<A HREF=$httpScriptName?$module+$tool+report+$typeDir+$device+$rest>$rest</A><BR>");
        }
      }
    } else {
      printDebug( 0, "Reading configdata for $reportName.");
      my ( $reportSection, $startTime, $stopTime );
      foreach my $entry (@info) {
        chomp( $entry );
        my ( $type, $rest ) = split(' ', $entry, 2);
        if ( "$type" eq "reportname" ) {
          $reportSection = $rest;
        } elsif ( "$reportSection" eq "$reportName" ) {
          if ( "$type" eq "timeslot" ) {
            ( $startTime, $stopTime ) = split(' ', $rest);
          } elsif ( "$type" eq "range" ) {
            my $rangeName = $rest;
            $rangeName =~ s/\s/_/g;
            printDebug( 0, "rangeName: $rangeName.");
            push( @rangeList, $rangeName );
            my ( $rangeEntry, $startIp, $stopIp, $type, $option ) = split(' ', $rest);
            my $startNum = numIpAddr($startIp);
            my $stopNum = numIpAddr($stopIp);
            $rangeId{$rangeName} = $rangeEntry;
            $rangeStart{$rangeName} = $startNum;
            $rangeStop{$rangeName} = $stopNum;
            print(" rangeId:$rangeEntry, startNum: $startNum, stopNum: $stopNum.");
          } elsif ( "$type" eq "port" ) {
            my ( $portName, $portInfo ) = split(' ', $rest);
            printDebug( 0, "portName: $portName, portInfo:$portInfo.");
            $portId{$portInfo} = $portName;
          }
        }
      }
      printDebug( 0, "Generating report $reportName for $device.");
      my %totalRange = ();
      my %totalPort = ();
      my @rangeList;
      my %detailsList = ();
      my $outDir = $SIMparam{'SIMgraphDir'};
      my $outPrefix = "traffic-details-$typeDir-$device-$reportName";
      my $startSecs = numSecs( $startTime );
      my $stopSecs = numSecs( $stopTime );
      my @devList = <$baseDir/*>;
      foreach my $dirEntry (@devList) {
        printDebug( 0, "Reading $dirEntry.");
        chdir $dirEntry;
        my @entries = <*>;
        foreach my $entry (@entries) {
#         printDebug( 0, " $entry ");
          my ( $source, $dest, $proto, $port ) = split('-', $entry);
          my $sourceType = testRange( $source );
          my $destType = testRange( $dest );
          my $rangeInfo = "$sourceType-_-$destType";
          if ( "$totalRange{$rangeInfo}" eq "" ) {
            # new list actions
            push(@rangeList, $rangeInfo);
            $totalRange{$rangeInfo} = 0;
            printFileLine("$outDir/$outPrefix-$rangeInfo","rangeinfo $rangeInfo", "source dest proto bytes\n");
          }
          my $numPort = $port * 1;
          my $portIdent;
          if ( $portId{"$numPort-$proto"} ne "" ) {
            $portIdent = $portId{"$numPort-$proto"};
          } else {
#           print(" $numPort-$proto");
            $portIdent = $portId{'rest'};
          }
          my $rangeDetails = "$sourceType-_-$destType-_-$portIdent";
#         print(" rangeDetails: $rangeDetails.");
          if ( "$totalPort{$rangeDetails}" eq "" ) {
            # new list actions
            $detailsList{$rangeInfo} = "$detailsList{$rangeInfo} $rangeDetails";
            $totalPort{$rangeDetails} = 0;
            printFileLine("$outDir/$outPrefix-$rangeDetails","rangeDetails $rangeDetails", "source dest proto bytes\n");
          }
          # count file and put results in hash for later reporting.
          my $fileTotal = countFileTotal( $entry, $startSecs, $stopSecs);
          $totalRange{$rangeInfo} = $totalRange{$rangeInfo} + $fileTotal;
          printFileLine("$outDir/$outPrefix-$rangeInfo","append","$source $dest $proto-$port $fileTotal\n");
          $totalPort{$rangeDetails} = $totalPort{$rangeDetails} + $fileTotal;
          printFileLine("$outDir/$outPrefix-$rangeDetails","append","$source $dest $proto-$port $fileTotal\n");
        }
      }
      my $grandTotal = 0;
      foreach my $entry (@rangeList) {
        $grandTotal = $grandTotal + $totalRange{$entry};
      }  
      my $htmlGraphDir = "graphs";
      printDebug( 0, "Generating totals, grandtotal = $grandTotal");
      print("<HR><TABLE>");
      print("<TR><TD COLSPAN=9>Report: $reportName, source: $typeDir, device: $device.</TD></TR>");;
      print("<TR><TD COLSPAN=9><BR>Breakdown analysis for network ranges.</TD></TR>");
      print("<TR><TD>Source</TD><TD COLSPAN=2>Destination</TD><TD ALIGN=right>Bytes</TD><TD ALIGN=right>Percent%</TD></TR>");
      my %dispPercValue = ();
      foreach my $entry (@rangeList) {
        my $percent = $totalRange{$entry} / $grandTotal * 100;
        my $dispPercent = sprintf("%.1f", $percent);
        # later used for sub reporting
        $dispPercValue{$entry} = $dispPercent;
        my ( $source, $dest ) = split('-_-', $entry);
        print("<TR><TD>$source</TD><TD COLSPAN=2>$dest</TD>
                   <TD ALIGN=right><A HREF=/$htmlGraphDir/$outPrefix-$entry>$totalRange{$entry}</A></TD>
                   <TD ALIGN=right>$dispPercent%</TD></TR>");
#       printDebug(0, "Total $entry: $totalRange{$entry}, $dispPercent%.");
      }
      # port breakdown per addres pair
      foreach my $entry (@rangeList) {
        my ( $sourceNet, $destNet ) = split('-_-', $entry);
        print("<TR><TD COLSPAN=9><BR>Port breakdown analysis range $sourceNet to $destNet.</TD></TR>");
        my @breakEntries = split(' ', $detailsList{$entry});
        my $breakTotal = 0;
        foreach my $entry (@breakEntries) {
#         print("<TR><TD COLSPAN=9>breakEntries: $entry $totalPort{$entry}.</TD></TR>");
          $breakTotal = $breakTotal + $totalPort{$entry};
        }
        foreach my $entry (@breakEntries) {
          my $dispPercent;
          if (( $totalPort{$entry} > 0 ) and ( $breakTotal > 0 )) {
            my $percent = $totalPort{$entry} / $breakTotal * 100;
            $dispPercent = sprintf("%.1f", $percent);
          } else {
            $dispPercent = "-";
          }
          my ( $source, $dest, $proto ) = split('-_-', $entry);
          print("<TR><TD>$source</TD><TD>$dest</TD><TD>$proto</TD>
                     <TD ALIGN=right><A HREF=/$htmlGraphDir/$outPrefix-$entry>$totalPort{$entry}</A></TD>
                     <TD ALIGN=right>$dispPercent%</TD></TR>");
        }
      }
      print("</TABLE>");
    }
  }
  print("</TD></TR></TABLE>");
}

#--------------------------- Main ---------------------------
printHead;


if ( "$action" eq "none" ) {
  $action = "display";
}
if ( "$action" eq "syslog" ) {
  analyseSyslog($option1, $option2);
} elsif ( "$action" eq "display" ) {
  display($option1, $option2, $option3, $option4);
} elsif ( "$action" eq "detail" ) {
  detail($option1, $option2, $option3);
} elsif ( "$action" eq "report" ) {
  report($option1, $option2, $option3);
} else {
  print("Oops, action $action not found.");
}
